﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Dycox.Collections
{
    public class CollectionBase<TItem> : System.Collections.ObjectModel.Collection<TItem>
    {
        public CollectionBase()
        {

        }

        protected virtual bool AllowsNulls
        {
            get { return false; }
        }

        protected virtual bool AllowsDuplicateItems
        {
            get { return false; }
        }

        protected virtual void AttachItem(TItem item)
        {
            if (item == null && !AllowsNulls)
                throw new ArgumentNullException("item");
            if (!AllowsDuplicateItems && this.Contains(item))
                throw new InvalidOperationException("This collection cotains the item already.");
        }

        protected virtual void DeattachItem(TItem item)
        {
        }

        protected override void ClearItems()
        {
            TItem[] array = new TItem[Count];
            this.CopyTo(array, 0);
            base.ClearItems();
            Exception error = null;

            foreach (TItem item in array)
            {
                try
                {
                    DeattachItem(item);
                }
                catch (Exception ex)
                {
                    error = ex;
                }
            }

            if (error != null)
                throw new System.Reflection.TargetInvocationException(error);
        }

        protected override void InsertItem(int index, TItem item)
        {
            AttachItem(item);
            base.InsertItem(index, item);
        }

        protected override void RemoveItem(int index)
        {
            TItem item = this[index];
            base.RemoveItem(index);
            DeattachItem(item);
        }

        protected override void SetItem(int index, TItem item)
        {
            TItem item0 = this[index];
            AttachItem(item);
            base.SetItem(index, item);
            DeattachItem(item0);
        }
    }
}
